package com.cow.framework.core.web;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest;

import com.cow.framework.core.base.BaseComponent;
import com.cow.framework.core.cache.RedisUtil;
import com.cow.framework.core.config.constant.MessageConstants;
import com.cow.framework.core.exception.BusinessException;
import com.cow.framework.core.exception.BusinessHint;
import com.cow.framework.core.log.NoLogUtil;
import com.cow.framework.core.log.VisitLog;
import com.cow.framework.core.log.VisitLogDAO;
import com.cow.framework.core.security.UrlMather;
import com.cow.framework.utils.json.FastJsonUtil;
import com.cow.framework.utils.web.IPUtil;
import com.cow.support.dto.UserSessionModel;

/**
 * Web交互拦截器
 * 
 * @author yangsj 
 */
@Aspect
@Component
public class InteractAspect extends BaseComponent{
	@Autowired
	VisitLogDAO visitLogDAO;
	@Autowired
	protected RedisUtil redisUtil;
	@Autowired
	private UrlMather urlMather;
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());  
	
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void interact(){}
    
    @Before("interact()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        //处理POST参数
        HttpServletRequest request = getRequest();   
        request.setCharacterEncoding("UTF-8"); 
        String method = request.getMethod();
        if ("POST".equals(method)) {
        	Object[] paramsArray = joinPoint.getArgs();
        	for(Object p:paramsArray){
        		if(p instanceof Map){
        			Map<String,Object> paraMap = (Map)p;
            		for(String key:paraMap.keySet()){
            			if(paraMap.get(key) != null && paraMap.get(key).equals("")){//空字符串转为null
            				paraMap.put(key, null);     				
            			}
            		}
        		}        		
        	}
        }
    }

    @Around("interact()")
    public Object doAround(ProceedingJoinPoint jp) throws Throwable {
    	HttpServletRequest request = getRequest();
        Map<String, Object> resultMap = new HashMap<String, Object>();       
        
        Object rvt = null;
        try{
        	if(!passUrl(request.getServletPath()) && !checkLogin(request,jp)){//未登录
            	throw new BusinessException("B1000",MessageConstants.B1000);         	
            }          	
        	        	
        	rvt = jp.proceed();
        	//请求异常不做包装直接返回
        	if(jp.getTarget() instanceof ErrorController || jp.getTarget() instanceof ResponseEntity || rvt instanceof ResponseEntity){
            	return rvt;
            }
        	
        	resultMap.put("code", "H0000"); 
        	resultMap.put("data", rvt);
        }catch(BusinessHint e){//业务提示
        	Map dataMap = new HashMap();
        	dataMap.put("msg", e.getMessage());
        	
        	resultMap.put("code", e.getCode());
        	resultMap.put("data", dataMap);
        }catch(BusinessException e){//业务异常
        	Map dataMap = new HashMap();
        	dataMap.put("msg", e.getMessage());
        	
        	resultMap.put("code", e.getCode());
        	resultMap.put("data", dataMap);   	
        }catch(Exception e){//系统异常
        	Map dataMap = new HashMap();
        	dataMap.put("msg", e.getMessage());
            	
        	resultMap.put("code", "S0000");
        	resultMap.put("data", dataMap);
        	//记录异常日志
        	StringWriter sw=new StringWriter();  
            PrintWriter pw=new PrintWriter(sw);
            e.printStackTrace(pw);
        	logger.error("errInfo.stackTrace:" + sw.toString());        	
        }
          
        return resultMap;  
    }
    
    private boolean checkLogin(HttpServletRequest request,ProceedingJoinPoint jp){
    	//登录验证        
        String token = request.getHeader("Authorization");   
        if(token != null){
        	UserSessionModel user = (UserSessionModel)redisUtil.get("userSession-" + token);
        	if(user == null){
        		user = (UserSessionModel)redisUtil.getCommon("userSession-" + token);
        	}   
        	
        	if(user != null){
        		request.getSession().setAttribute("userSession", user);
        		
        		//判断url访问权限
        		urlMather.checkUrl(request.getServletPath());
        		
        		//记录日志
        		if(user.getUserInfo() != null){
        			log(user.getUserInfo().getUserid().intValue(),jp);
        		}
        		//重新设置过期时间
        		redisUtil.expire("userSession-" + token,new Long(parameterUtil.get("sessionExpireTime")));
        		return true;
        	}
        }else if(active.equals("dev")){
        	return true;
        }        
    	
    	return false;
    }
    
    private boolean passUrl(String url){
    	if(url.equals("/comm/login/onLogin")||url.equals("/file/viewImgByUrl")||url.startsWith("/file/download")||url.equals("/comm/login/getCheckCode")||url.equals("/ping/getStatus")){
    		return true;
    	}
    	return false;
    }
    
    private boolean noLog(String url){
    	return NoLogUtil.isNoLog(url);
    }
    
    private void log(Integer userId,ProceedingJoinPoint joinPoint){
    	 // 接收到请求，记录请求内容
        HttpServletRequest request = getRequest();        
        String ip = IPUtil.getIpAddress(request);
        String uri = request.getRequestURI();
        String method = request.getMethod();
        String params = "";
//        if ("POST".equals(method)) {
//        	Object[] paramsArray = joinPoint.getArgs();
//        	try{
//        		params = argsArrayToString(paramsArray);
//        	}catch(Exception e){
//        		e.printStackTrace();
//        	}
//            
//        } else {
//            params = request.getQueryString();
//        }
//        
//        if(params != null && params.length() > 500){
//        	params = params.substring(0, 499);
//        }
        
        if(!noLog(uri)){
        	//记录访问日志
            VisitLog log = new VisitLog();
            log.setIp(ip);
            log.setUrl(uri);
            log.setUserId(userId);
            log.setVisitTime(new Date());
            visitLogDAO.save(log);          
        }        
    }
    
    private HttpServletRequest getRequest(){
    	// 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes.getRequest();
    }
    
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            for (int i = 0; i < paramsArray.length; i++) {
            	if(paramsArray[i] instanceof AbstractMultipartHttpServletRequest) continue;
                Object jsonObj = FastJsonUtil.toJSONString(paramsArray[i]);
                params += jsonObj.toString() + " ";
            }
        }
        return params.trim();
    }
}